/**
 * @ Author: luoqi
 * @ Create Time: 2024-07-12 09:27
 * @ Modified by: luoqi
 * @ Modified time: 2024-10-13 23:41
 * @ Description:
 */
#include <stdarg.h>
#include <stdbool.h>
#include <stdio.h>
#include "bsp.h"

extern void SystemClock_Config(void);

static int bsp_rcc_reset()
{
    RCC_ClkInitTypeDef RCC_ClkInitStruct = { 0 };
    RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK;
    RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
    if(HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK) {
        Error_Handler();
    }
    return 0;
}

int bsp_init(void)
{
    HAL_Init();
    bsp_rcc_reset();
    SystemClock_Config();
    MX_GPIO_Init();
    MX_USART1_UART_Init();

    bsp_printf("\033[H\033[2J");
    bsp_printf("  ___  ___  ___   ___ _____\r\n");
    bsp_printf(" / _ \\| _ )/ _ \\ / _ \\_   _|\r\n");
    bsp_printf("| (_) | _ \\ (_) | (_) || |\r\n");
    bsp_printf(" \\__\\_\\___/\\___/ \\___/ |_|\r\n");
    bsp_printf(" QBOOT FIRMWARE, %s, %s\r\n", __DATE__, __TIME__);
    bsp_printf(" Designed by luoqi\r\n");

    return 0;
}

int bsp_deinit()
{
    HAL_DeInit();
    return 0;
}

int bsp_printf(const char *fmt, ...)
{
    static char buf[256] = { 0 };
    int ret;
    va_list args;
    va_start(args, fmt);
    int sz = vsnprintf(buf, sizeof(buf) - 1, fmt, args);
    va_end(args);
    if(sz < 0) {
        ret = HAL_UART_Transmit(&huart1, (uint8_t *)" #! Print parse faild\r\n", 25, 100);
    }
    ret = HAL_UART_Transmit(&huart1, (uint8_t *)buf, sz, 100);
    return ret;
}

int bsp_uart1_recv(uint8_t *data, uint32_t len, uint32_t timeout)
{
    int ret = HAL_UART_Receive(&huart1, data, len, timeout);
    if(ret == HAL_OK) {
        return len;
    } else {
        return ret;
    }
}

int bsp_uart1_send(const uint8_t *data, uint32_t sz, uint32_t timeout)
{
    return HAL_UART_Transmit(&huart1, data, sz, timeout);
}

void bsp_led_set(BspLedState state)
{
    switch(state) {
    case BSP_LED_ON:
        HAL_GPIO_WritePin(BLINK_GPIO_Port, BLINK_Pin, GPIO_PIN_RESET);
        break;
    case BSP_LED_OFF:
        HAL_GPIO_WritePin(BLINK_GPIO_Port, BLINK_Pin, GPIO_PIN_SET);
        break;
    default:
        break;
    }
}

static uint32_t _blink_lfrq = 300;
static uint32_t _blink_hfrq = 100;

void blink()
{
    static bool state = false;
    static uint32_t cnt = 0;
    static uint32_t frq = 0;
    if(cnt++ > frq) {
        state = !state;
        if(state) {
            bsp_led_set(BSP_LED_OFF);
            frq = _blink_hfrq;
        } else {
            bsp_led_set(BSP_LED_ON);
            frq = _blink_lfrq;
        }
        cnt = 0;
    }
}

void bsp_blink_set(uint32_t lfrq, uint32_t hfrq)
{
    if(lfrq > 0) {
        _blink_lfrq = lfrq;
    }
    if(hfrq > 0) {
        _blink_hfrq = hfrq;
    }
}

void bsp_mdelay(uint32_t ms)
{
    HAL_Delay(ms);
}

void bsp_reboot(void)
{
    __disable_irq();
    HAL_NVIC_SystemReset();
}

uint32_t bsp_strlen(const char *s)
{
    uint32_t len = 0;
    while(*s++ != '\0') {
        len++;
    }
    return len;
}
